package com.example.demo7;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import java.util.*;

public class RPGgame extends Application {

    // 游戏窗口和地图尺寸常量
    public static final int WIDTH = 1555;          // 窗口宽度
    public static final int HEIGHT = 972;          // 窗口高度
    public static final int TILE_SIZE = 40;        // 每个瓦片的大小(像素)
    public static final int PLAYER_SIZE = 30;      // 玩家角色大小
    public static final int ENEMY_SIZE = 30;       // 敌人大小
    public static final int PROJECTILE_SIZE = 8;    // 子弹大小

    private Stage primaryStage;
    private StartScreen startScreen;
    private Scene gameScene;
    private boolean twoPlayerMode = false;

    // JavaFX图形组件
    public Canvas canvas;          // 画布，用于绘制游戏内容
    public GraphicsContext gc;      // 图形上下文，提供绘图方法

    // 玩家属性
    public static double playerX = WIDTH / 2;     // 玩家X坐标
    public static double playerY = HEIGHT / 2;    // 玩家Y坐标
    public double playerSpeed = 3;         // 玩家移动速度
    public int playerHealth = 100;         // 玩家当前生命值
    public int playerMaxHealth = 100;      // 玩家最大生命值
    public int playerDamage = 10;          // 玩家攻击伤害
    public boolean isInvincible = true;   // 玩家是否处于无敌状态
    public int invincibleTimer = 0;        // 无敌状态计时器

    // 敌人列表
    private List<Enemy> enemies = new ArrayList<>();

    // 子弹列表
    private List<Projectile> projectiles = new ArrayList<>();

    // 房间和地图
    private static int[][] room = new int[WIDTH / TILE_SIZE][HEIGHT / TILE_SIZE]; // 房间网格，0=空地，1=墙
    private Random random = new Random(); // 随机数生成器

    // 游戏状态
    private boolean gameOver = false; // 游戏是否结束
    private boolean gameWin = false;  // 游戏是否胜利
    private int score = 0;            // 玩家得分
    private int level = 1;           // 当前关卡

    // 按键状态
    private boolean upPressed, downPressed, leftPressed, rightPressed; // 移动按键状态
    private boolean spacePressed; // 射击按键状态
    private boolean player2UpPressed, player2DownPressed, player2LeftPressed, player2RightPressed;
    private boolean player2ShootPressed;
    private double player2X = WIDTH / 2 + 50;
    private double player2Y = HEIGHT / 2;
    // 玩家朝向
    private double playerAngle = 0; // 玩家面朝方向(弧度)

    @Override
    public void start(Stage primaryStage) {
        this.primaryStage = primaryStage;

        primaryStage.setTitle("美少女RPG冒险游戏");

        // 创建开始界面
        startScreen = new StartScreen(
                () -> startGame(false), // 单人模式回调
                () -> startGame(true)   // 双人模式回调
        );

        // 设置初始场景为开始界面
        primaryStage.setScene(startScreen.getScene());
        primaryStage.setResizable(false);
        primaryStage.show();
    }

    // 新增方法：启动游戏
    private void startGame(boolean twoPlayerMode) {
        this.twoPlayerMode = twoPlayerMode;

        // 初始化游戏界面
        Pane root = new Pane();
        canvas = new Canvas(WIDTH, HEIGHT);
        gc = canvas.getGraphicsContext2D();
        root.getChildren().add(canvas);

        // 创建场景并设置舞台
        Scene gameScene = new Scene(root, WIDTH, HEIGHT);
        primaryStage.setScene(gameScene);

        // 初始化游戏
        initGame();

        // 设置按键监听器
        gameScene.setOnKeyPressed(e -> {
            if (gameOver || gameWin) {
                // 游戏结束或胜利时，只响应R键重新开始
                if (e.getCode() == KeyCode.R) {
                    resetGame();
                }
                return;
            }

            // 设置移动按键状态
            if (e.getCode() == KeyCode.W) upPressed = true;
            if (e.getCode() == KeyCode.S) downPressed = true;
            if (e.getCode() == KeyCode.A) leftPressed = true;
            if (e.getCode() == KeyCode.D) rightPressed = true;
            if (e.getCode() == KeyCode.SPACE) spacePressed = true;

            // 双人模式下的玩家2控制
            if (twoPlayerMode) {
                if (e.getCode() == KeyCode.UP) player2UpPressed = true;
                if (e.getCode() == KeyCode.DOWN) player2DownPressed = true;
                if (e.getCode() == KeyCode.LEFT) player2LeftPressed = true;
                if (e.getCode() == KeyCode.RIGHT) player2RightPressed = true;
                if (e.getCode() == KeyCode.ENTER) player2ShootPressed = true;
            }
        });

        gameScene.setOnKeyReleased(e -> {
            // 释放按键时重置状态
            if (e.getCode() == KeyCode.W) upPressed = false;
            if (e.getCode() == KeyCode.S) downPressed = false;
            if (e.getCode() == KeyCode.A) leftPressed = false;
            if (e.getCode() == KeyCode.D) rightPressed = false;
            if (e.getCode() == KeyCode.SPACE) spacePressed = false;

            // 双人模式下的玩家2控制
            if (twoPlayerMode) {
                if (e.getCode() == KeyCode.UP) player2UpPressed = false;
                if (e.getCode() == KeyCode.DOWN) player2DownPressed = false;
                if (e.getCode() == KeyCode.LEFT) player2LeftPressed = false;
                if (e.getCode() == KeyCode.RIGHT) player2RightPressed = false;
                if (e.getCode() == KeyCode.ENTER) player2ShootPressed = false;
            }
        });

        // 创建并启动游戏循环
        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                update(); // 更新游戏状态
                render(); // 渲染游戏画面
            }
        };
        timer.start();
    }

    /**
     * 初始化游戏
     */
    private void initGame() {
        generateRoom();   // 生成房间布局
        spawnEnemies(5);  // 生成初始敌人
    }

    /**
     * 生成房间布局
     */
    private void generateRoom() {
        // 清空房间，将所有格子设为空地
        for (int x = 0; x < room.length; x++) {
            for (int y = 0; y < room[0].length; y++) {
                room[x][y] = 0; // 0表示空地
            }
        }

        // 添加边界墙
        for (int x = 0; x < room.length; x++) {
            room[x][0] = 1; // 1表示墙
            room[x][room[0].length - 1] = 1;
        }
        for (int y = 0; y < room[0].length; y++) {
            room[0][y] = 1;
            room[room.length - 1][y] = 1;
        }

        // 随机添加一些障碍物
        for (int i = 0; i < 20; i++) {
            int x = random.nextInt(room.length - 4) + 2;
            int y = random.nextInt(room[0].length - 4) + 2;
            room[x][y] = 1;
        }
    }

    /**
     * 生成敌人
     *
     * @param count 要生成的敌人数量
     */
    private void spawnEnemies(int count) {
        enemies.clear(); // 清空敌人列表
        for (int i = 0; i < count; i++) {
            // 确保敌人生成位置不靠近玩家
            double x, y;
            do {
                x = random.nextInt(WIDTH - 100) + 50;
                y = random.nextInt(HEIGHT - 100) + 50;
            } while (Math.abs(x - playerX) < 200 && Math.abs(y - playerY) < 200);

            int type = random.nextInt(3); // 随机选择敌人类型(0-2)
            enemies.add(new Enemy(x, y, type));
        }
    }

    /**
     * 更新游戏状态
     */
    private void update() {
        if (gameOver || gameWin) return; // 游戏结束或胜利时不更新

        updatePlayer();     // 更新玩家状态
        updateEnemies();    // 更新敌人状态
        updateProjectiles(); // 更新子弹状态

        // 处理玩家无敌状态
        if (isInvincible) {
            invincibleTimer--;
            if (invincibleTimer <= 0) {
                isInvincible = false;
            }
        }

        // 检查游戏胜利条件(所有敌人被消灭)
        if (enemies.isEmpty()) {
            level++; // 增加关卡
            if (level > 3) {
                gameWin = true; // 通关
            } else {
                // 生成下一关敌人并恢复玩家生命值
                spawnEnemies(5 + level * 2);
                playerHealth = playerMaxHealth;
            }
        }
    }

    /**
     * 更新玩家状态
     */
    private void updatePlayer() {
        double prevX = playerX; // 保存之前的位置用于碰撞检测
        double prevY = playerY;

        // 计算移动方向向量
        double dx = 0, dy = 0;
        if (upPressed) dy -= 1;
        if (downPressed) dy += 1;
        if (leftPressed) dx -= 1;
        if (rightPressed) dx += 1;

        // 标准化移动向量(确保斜向移动速度不变)
        double length = Math.sqrt(dx * dx + dy * dy);
        if (length != 0) {
            dx /= length;
            dy /= length;

            // 更新玩家朝向
            playerAngle = Math.atan2(dy, dx);
        }

        // 应用速度
        playerX += dx * playerSpeed;
        playerY += dy * playerSpeed;

        // 边界检查
        if (playerX < PLAYER_SIZE) playerX = PLAYER_SIZE;
        if (playerX > WIDTH - PLAYER_SIZE) playerX = WIDTH - PLAYER_SIZE;
        if (playerY < PLAYER_SIZE) playerY = PLAYER_SIZE;
        if (playerY > HEIGHT - PLAYER_SIZE) playerY = HEIGHT - PLAYER_SIZE;

        // 障碍物碰撞检测
        if (checkCollisionWithWalls(playerX, playerY, PLAYER_SIZE / 2)) {
            // 如果碰撞，恢复之前的位置
            playerX = prevX;
            playerY = prevY;
        }

        // 处理射击
        if (spacePressed) {
            shoot();
            spacePressed = false; // 单次射击
        }
    }

    /**
     * 玩家射击
     */
    private void shoot() {
        // 根据玩家朝向计算子弹方向
        double angle = playerAngle;
        double speed = 8;
        double dx = Math.cos(angle) * speed;
        double dy = Math.sin(angle) * speed;

        // 创建新子弹并添加到列表
        projectiles.add(new Projectile(playerX, playerY, dx, dy, playerDamage, false));
    }

    /**
     * 更新所有敌人状态
     */
    private void updateEnemies() {
        Iterator<Enemy> iterator = enemies.iterator();
        while (iterator.hasNext()) {
            Enemy enemy = iterator.next();
            enemy.update(playerX, playerY); // 更新敌人位置

            // 检测敌人与玩家碰撞
            double dist = Math.sqrt(Math.pow(playerX - enemy.x, 2) + Math.pow(playerY - enemy.y, 2));
            if (dist < PLAYER_SIZE / 2 + ENEMY_SIZE / 2) {
                if (!isInvincible) {
                    // 玩家受到伤害并进入无敌状态
                    playerHealth -= enemy.damage;
                    isInvincible = true;
                    invincibleTimer = 60; // 1秒无敌时间(60帧)
                    if (playerHealth <= 0) {
                        gameOver = true; // 玩家生命值<=0，游戏结束
                    }
                }
            }

            // 敌人射击
            if (enemy.canShoot()) {
                // 计算朝向玩家的角度
                double angle = Math.atan2(playerY - enemy.y, playerX - enemy.x);
                double speed = 5;
                double dx = Math.cos(angle) * speed;
                double dy = Math.sin(angle) * speed;

                // 添加敌人子弹
                projectiles.add(new Projectile(enemy.x, enemy.y, dx, dy, enemy.damage / 2, true));
            }
        }
    }

    /**
     * 更新所有子弹状态
     */
    private void updateProjectiles() {
        Iterator<Projectile> iterator = projectiles.iterator();
        while (iterator.hasNext()) {
            Projectile proj = iterator.next();
            proj.update(); // 更新子弹位置

            // 边界检查
            if (proj.x < 0 || proj.x > WIDTH || proj.y < 0 || proj.y > HEIGHT) {
                iterator.remove();
                continue;
            }

            // 障碍物碰撞检查
            if (checkCollisionWithWalls(proj.x, proj.y, PROJECTILE_SIZE / 2)) {
                iterator.remove();
                continue;
            }

            // 玩家子弹击中敌人
            if (!proj.isEnemyProjectile) {
                for (Enemy enemy : enemies) {
                    double dist = Math.sqrt(Math.pow(proj.x - enemy.x, 2) + Math.pow(proj.y - enemy.y, 2));
                    if (dist < PROJECTILE_SIZE / 2 + ENEMY_SIZE / 2) {
                        enemy.takeDamage(proj.damage); // 敌人受到伤害
                        if (enemy.health <= 0) {
                            enemies.remove(enemy); // 敌人生命值<=0，移除敌人
                            score += 100; // 增加分数
                        }
                        iterator.remove(); // 移除子弹
                        break;
                    }
                }
            }
            // 敌人子弹击中玩家
            else if (!isInvincible) {
                double dist = Math.sqrt(Math.pow(proj.x - playerX, 2) + Math.pow(proj.y - playerY, 2));
                if (dist < PROJECTILE_SIZE / 2 + PLAYER_SIZE / 2) {
                    playerHealth -= proj.damage;
                    isInvincible = true;
                    invincibleTimer = 60;
                    iterator.remove();
                    if (playerHealth <= 0) {
                        gameOver = true;
                    }
                }
            }
        }
    }

    /**
     * 检测与墙壁的碰撞
     *
     * @param x      检测点的X坐标
     * @param y      检测点的Y坐标
     * @param radius 检测半径
     * @return 是否发生碰撞
     */
    public static boolean checkCollisionWithWalls(double x, double y, double radius) {
        // 将坐标转换为网格坐标
        int gridX = (int) (x / TILE_SIZE);
        int gridY = (int) (y / TILE_SIZE);

        // 检查周围3x3网格
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                int checkX = gridX + dx;
                int checkY = gridY + dy;

                // 检查网格是否有效且是墙
                if (checkX >= 0 && checkX < room.length && checkY >= 0 && checkY < room[0].length) {
                    if (room[checkX][checkY] == 1) {
                        // 计算到墙中心的距离
                        double wallCenterX = checkX * TILE_SIZE + TILE_SIZE / 2;
                        double wallCenterY = checkY * TILE_SIZE + TILE_SIZE / 2;

                        double distX = Math.abs(x - wallCenterX);
                        double distY = Math.abs(y - wallCenterY);

                        // 简单的矩形碰撞检测
                        if (distX < radius + TILE_SIZE / 2 && distY < radius + TILE_SIZE / 2) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * 渲染游戏画面
     */
    private void render() {
        gc.clearRect(0, 0, WIDTH, HEIGHT); // 清空画布

        // 绘制黑色背景
        gc.setFill(Color.BLACK);
        gc.fillRect(0, 0, WIDTH, HEIGHT);

        // 绘制房间
        for (int x = 0; x < room.length; x++) {
            for (int y = 0; y < room[0].length; y++) {
                if (room[x][y] == 1) { // 墙
                    gc.setFill(Color.GRAY);
                    gc.fillRect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                    gc.setStroke(Color.DARKGRAY);
                    gc.strokeRect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                }
            }
        }

        // 绘制所有敌人
        for (Enemy enemy : enemies) {
            enemy.draw(gc);
        }

        // 绘制所有子弹
        for (Projectile proj : projectiles) {
            proj.draw(gc);
        }

        drawPlayer(); // 绘制玩家
        drawUI();     // 绘制UI

        // 绘制游戏状态
        if (gameOver) {
            drawGameOver();
        } else if (gameWin) {
            drawGameWin();
        }
    }

    /**
     * 绘制玩家
     */
    private void drawPlayer() {
        // 玩家颜色(无敌时闪烁)
        if (isInvincible && invincibleTimer % 10 < 5) {
            gc.setFill(Color.LIGHTBLUE); // 无敌闪烁效果
        } else {
            gc.setFill(Color.BLUE); // 正常颜色
        }

        // 绘制玩家圆形
        gc.fillOval(playerX - PLAYER_SIZE / 2, playerY - PLAYER_SIZE / 2, PLAYER_SIZE, PLAYER_SIZE);

        // 绘制玩家朝向指示器
        double indicatorLength = PLAYER_SIZE * 0.8;
        double indicatorX = playerX + Math.cos(playerAngle) * indicatorLength / 2;
        double indicatorY = playerY + Math.sin(playerAngle) * indicatorLength / 2;

        gc.setStroke(Color.WHITE);
        gc.setLineWidth(3);
        gc.strokeLine(playerX, playerY, indicatorX, indicatorY);
    }

    /**
     * 绘制用户界面
     */
    private void drawUI() {
        // 绘制生命值条背景
        double barWidth = 200;
        double barHeight = 20;
        double barX = 20;
        double barY = 20;

        // 生命值条背景(暗红色)
        gc.setFill(Color.DARKRED);
        gc.fillRect(barX, barY, barWidth, barHeight);

        // 当前生命值(红色)
        double healthPercent = (double) playerHealth / playerMaxHealth;
        gc.setFill(Color.RED);
        gc.fillRect(barX, barY, barWidth * healthPercent, barHeight);

        // 生命值条边框
        gc.setStroke(Color.WHITE);
        gc.setLineWidth(2);
        gc.strokeRect(barX, barY, barWidth, barHeight);

        // 生命值文本
        gc.setFill(Color.WHITE);
        gc.setFont(Font.font(16));
        gc.fillText("生命值: " + playerHealth + "/" + playerMaxHealth, barX + 5, barY + barHeight - 5);

        // 分数和等级
        gc.fillText("分数: " + score, barX, barY + barHeight + 25);
        gc.fillText("关卡: " + level, barX, barY + barHeight + 50);

        // 武器信息
        gc.fillText("武器: 手枪 (伤害: " + playerDamage + ")", barX, barY + barHeight + 75);
    }

    /**
     * 绘制游戏结束画面
     */
    private void drawGameOver() {
        // 半透明黑色背景
        gc.setFill(Color.rgb(0, 0, 0, 0.7));
        gc.fillRect(0, 0, WIDTH, HEIGHT);

        // 游戏结束文字
        gc.setFill(Color.RED);
        gc.setFont(Font.font(48));
        gc.fillText("游戏结束", WIDTH / 2 - 100, HEIGHT / 2 - 50);

        // 分数和重新开始提示
        gc.setFill(Color.WHITE);
        gc.setFont(Font.font(24));
        gc.fillText("最终分数: " + score, WIDTH / 2 - 70, HEIGHT / 2 + 20);
        gc.fillText("按 R 键重新开始", WIDTH / 2 - 100, HEIGHT / 2 + 70);
    }

    /**
     * 绘制游戏胜利画面
     */
    private void drawGameWin() {
        // 半透明黑色背景
        gc.setFill(Color.rgb(0, 0, 0, 0.7));
        gc.fillRect(0, 0, WIDTH, HEIGHT);

        // 胜利文字
        gc.setFill(Color.GOLD);
        gc.setFont(Font.font(48));
        gc.fillText("胜利!", WIDTH / 2 - 60, HEIGHT / 2 - 50);

        // 分数和重新开始提示
        gc.setFill(Color.WHITE);
        gc.setFont(Font.font(24));
        gc.fillText("最终分数: " + score, WIDTH / 2 - 70, HEIGHT / 2 + 20);
        gc.fillText("按 R 键重新开始", WIDTH / 2 - 100, HEIGHT / 2 + 70);
    }

    /**
     * 重置游戏
     */
    private void resetGame() {
        // 重置玩家属性
        playerX = WIDTH / 2;
        playerY = HEIGHT / 2;
        playerHealth = playerMaxHealth;
        isInvincible = false;
        invincibleTimer = 0;

        // 重置游戏状态
        gameOver = false;
        gameWin = false;
        score = 0;
        level = 1;

        // 清空子弹列表
        projectiles.clear();

        // 重新生成房间和敌人
        generateRoom();
        spawnEnemies(5);
    }

    public static void main(String[] args) {
        launch(args); // 启动JavaFX应用
    }
}
